import { List } from 'immutable';
import ACTION from '../constant/action-type';

const Commands = {
  updateValue: (editor, properties) => {
    const { value } = editor;
    editor.applyAction(ACTION.UPDATE_VALUE, {
      value,
      properties,
    });
  },
  saveHistory: (editor, action) => {
    const { isSave, value, actionStack } = editor;
    if (isSave === false || !action.canUndo) {
      return;
    }
    let actions = List([action]);
    let { undoStack } = value;
    const lastActions = undoStack.last();
    if (lastActions && lastActions.size > 0) {
      if (actionStack.size > 0) {
        actions = lastActions.push(action);
        undoStack = undoStack.pop();
      }
    }
    undoStack = undoStack.push(actions);

    if (undoStack.size > 20) {
      undoStack.pop();
    }
    const redoStack = List();
    editor.withoutSaving(editor => {
      editor.updateValue({ undoStack, redoStack });
    });
  },
  undo: editor => {
    const { value } = editor;
    const batchUpdate = value.undoStack.last();
    if (!batchUpdate) {
      return;
    }
    editor.withoutSaving(editor => {
      batchUpdate.reverse().forEach(action => {
        const revert = action.revert();
        if (revert) {
          editor.apply(revert);
        }
      });
      const undoStack = value.undoStack.pop();
      const redoStack = value.redoStack.push(batchUpdate);
      editor.updateValue({ undoStack, redoStack });
    });
  },
  redo: editor => {
    const { value } = editor;
    const batchUpdate = value.redoStack.last();
    if (!batchUpdate) {
      return;
    }
    editor.withoutSaving(editor => {
      batchUpdate.reverse().forEach(action => {
        editor.apply(action);
      });
      const undoStack = value.undoStack.push(batchUpdate);
      const redoStack = value.redoStack.pop();
      editor.updateValue({ undoStack, redoStack });
    });
  },
  withoutSaving: (editor, fn) => {
    const value = editor.isSave;
    editor.isSave = false;
    fn(editor);
    editor.isSave = value;
  },
};

export default Commands;
